Поскольку на самом деле нам нужно реализовать не только систему резервирования гостиничных номеров, но и систему резервирования других ресурсов, включая резервирование авиабилетов и автомобилей напрокат, необходимо тщательно продумать механизм абстракции С одной стороны, чем больше функций мы сможем включить в базовый класс, тем меньше останется работы при реализации каждой конкретной системы резервирования. С другой стороны, если базовый класс будет содержать слишком много функций, то множество задач, для решения которых его можно применить, уменьшится При качественном проектировании необходимо определить оптимальное множество функций, включаемых в базовый класс.
Еще одним свойством "хороших" абстракций является то, что их не задевают даже серьезные изменения в реализации. Далее в этой книге будет показано, что вносить изменения в абстракции системы резервирования гостиничных номеров не придется даже тогда, когда мы реализуем ее с помощью базы данных SQL Server.
Упомянутые абстракции в C++ представлены с помощью абстрактных классов, описанных в файле Broker.срр, расположенном в папке CaseStudy для этой главы
Класс Reservabie (Резервируемый объект, ресурс)
В качестве первой абстракции выберем объект, который мы будем резервировать. Назовем эту абстракцию просто Reservabie (Резервируемый объект, ресурс). Основной момент в резервировании — это использование ресурса Нельзя, чтобы один ресурс был зарезервирован несколькими пользователями одновременно, поэтому основным атрибутом Reservabie (Резервируемый объект, ресурс) является capacity (объем имеющих-
ся ресурсов). Например, в гостинице — 100 номеров, авиарейс имеет 250 мест Для объекта Reservable (Резервируемый объект, ресурс) также потребуется уникальный идентификатор, который мы обозначим unitid (Вместо более длинного, неудобного имени reservableid, было выбрано более короткое unitid. Позже мы будем использовать слово unit (объект, единица) и в других именах Например, метод для добавления резервируемого объекта назовем AddUnit)
В приложениях мы введем дополнительный атрибут cost (стоимость). Для гостиничного номера — это его стоимость за сутки, для авиабилета — цена и т д Обратите внимание на то, что к некоторым резервируемым объектам этот атрибут может быть неприменим Например, стоимость зала заседаний для компании может и не быть определена, но поскольку наше приложение будет использоваться в коммерческих целях, то атрибут cost (стоимость) нужно включить в модель
Упрощения
public _gc _abstract class Reservable
// сборщик мусора - класс Reservable
{
static private int nextid = 0; // статический частный
protected: // защищенный
int unitid; public:
int capacity; // вместимость
Decimal cost; // Десятичная стоимость;
Reservable(int capacity, Decimal cost)
// вместимость, Десятичная стоимость
{
this->capacity = capacity;
// вместимость
this->cost = cost;
// стоимость
unitid = nextid++;
}
};
В конструкторе можно задать атрибуты capacity (объем имеющихся ресурсов) и cost (стоимость) Значение поля unitid генерируется автоматически с помощью статической переменной. Минимальное значение этого атрибута — ноль, так как мы будем использовать его в качестве одного из индексов двумерного массива, который содержит информацию о количестве клиентов, резервирующих данный объект на конкретную дату.
Роль спецификаторов управления доступом private (частный), internal (внутренний) и protected (защищенный) мы обсудим позже
Резервирование
Ксиди клиент резервирует объект, создается запись о резервировании. Класс Reser-v,u j on (Резервирование) содержит информацию о резервировании.
public _gc _abstract class Reservation
// сборщик мусора - абстрактный класс Резервирование
{
public:
int Reservationld;
int Unitld;
DateTime Date; // Дата
int NumberDays;
static private int nextReservationld = 1; // статический
// частный
Reservation() // Резервирование
{
Reservationld = nextReservation!d++;
}
};
Значение поля Reservationld генерируется автоматически. Поле Unitld идентифицирует зарезервированный объект. Поле Date (Дата) определяет начальную дату резервирования, поле NumberDays определяет количество дней, на которые зарезервирован объект.
Брокер
Третья абстракция, класс Broker (Брокер), — это модель брокера, который отвечает за резервирование разнообразных объектов. Данная абстракция реализована в виде абстрактного класса. Этот класс содержит список резервируемых объектов, представленных в виде массива units, и список резервирований, представленных в виде массива reservations (резервирования). С помощью двумерного массива numCost отслеживается количество клиентов, которые зарезервировали объект на указанный день.
public _gc _abstract class Broker // сборщик мусора - абстрактный
класс Брокера ' -{
private: // частный
int MaxDay;
static const int MAXRESERVATION = 10; // статическая константа
static int nextReservation = 0;
static int nextUnit = 0;
int numCust [,];
protected: // защищенный
Reservation *reservations[]; // Резервирование
Reservable *units[];
public:
Broker(int MaxDay, int MaxUnit) // Брокер
{
this->MaxDay = MaxDay;
numCust = new int _gc [MaxDay, MaxUnit];
units = new Reservable*[MaxUnit];
reservations = new Reservation*[MAXRESERVATION];
// резервирование }
Структура ReservationResult
Для возвращения результата резервирования используется простая структура ReservationResult.
public _gc struct ReservationResult
// сборщик мусора - struct ReservationResult
{
public:
int Reservationld;
Decimal ReservationCost; // Десятичное число ReservationCost
Decimal Rate; // Десятичное число - цена
String *Comment;
};
Поле Rate (Цена) определяет стоимость резервируемого объекта за один день. Значение поля ReservationCost определяет полную стоимость резервирования объекта, которая равняется количеству дней, умноженному на стоимость резервирования за один день. Если возникают проблемы, в качестве Reservationld возвращается -1. причем в поле Comment (Примечание) описывается проблема. Структура создана таким образом, что информация о результате будет передаваться в любом случае, например, ее можно использовать в Web-службах, которые не поддерживают обработку исключений.